package it.univpm.diiga.memorysim.kernel.shared;



import it.univpm.diiga.memorysim.kernel.shared.tree.MovingBox;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;


public class Parameters {
	
	// Valori di prova per gli algoritmi
	private String[] memCentral=new String[]{"Random"};
	private String[] memSecondary=new String[]{"Dummy"};
	
	//Caratteristiche Sistema
	private static int dimMem =450;
	private static int dimSwap = 0;
	private static int dimPage=0; // in byte
	private static int dimSOMemory=200; //area riservata al sistema operativo
	
	//HHD 
	private static int dimension; //  [Gb]
	private static int seekTime;
	private static int blockSize;  //-> trasfer= blocksize/trasferrate
	private static int trasferRate;
	private static int revolutionTime; // -> latencytime= revolutiontime/2
	
	//Elenco dei processi
	private static List<ProcessRequest> processList;
	private static ArrayList <FileRequest> fileList;
	
	
	
	
	// Simulation sequence 
	//private static ArrayList<it.univpm.diiga.memorysim.kernel.shared.StepProcSim> SequenzaSimulazioneProcessi;
	//private static ArrayList <it.univpm.diiga.memorysim.kernel.shared.StepFileSim> SequenzaSimulazioneFile;
	//private static List<MemoryElement> sequence=new ArrayList<MemoryElement>();

	/*
	 * STRUTTURE MEMORIA
	 */
	private static Hashtable<Integer, MemoryElement> SOMemory=new Hashtable<Integer, MemoryElement>();
	private static int positionSOMemory=0;
	
	private static List<MemoryElement> processMemory=new ArrayList<MemoryElement>();
	private static int positionProcessMemory=0;
	private static int dimProcessMem=dimMem-dimSOMemory;
	//private static int dimProcessMem=300;
	
	private static List<MemoryElement> swap=new ArrayList<MemoryElement>();
	private static int positionSwap=0;
	
	private static List<MemoryElement> emptyBlockMem = new ArrayList<MemoryElement>();
	private static List<MemoryElement> emptyBlockSwap = new ArrayList<MemoryElement>();
	
	private static List<Algorithm> algorithmListPag = new ArrayList<Algorithm>();
	private static List<Algorithm> algorithmListSeg = new ArrayList<Algorithm>();
	private static Algorithm algorithmSelected;
	
	//private static ArrayList<Integer> memory;
	
	private static MovingBox root_disk;
	
	
	public static void setAlgorithmSelectedPag(Algorithm alg){
		algorithmSelected = alg;
	}
	
	public static void setAlgorithmSelectedSeg(Algorithm alg){
		algorithmSelected = alg;
	}
	
	public static void setAlgorithmSelectedPag(int position){
		if (algorithmListPag.size()>0)
			algorithmSelected = algorithmListPag.get(position);
	}
	
	public static void setAlgorithmSelectedSeg(int position){
		if (algorithmListSeg.size()>0)
			algorithmSelected = algorithmListSeg.get(position);
	}
	
	public static void setDimPage(int dimPagePara){
		dimPage=dimPagePara;
	}

	
	public static int getDimPage(){
		return dimPage;
	}
	
	public void setProcessList(List<ProcessRequest> processListPara){
		processList=processListPara;
	}
	
	public static  List<ProcessRequest> getProcessList(){
		return processList;
	}
	
	public static Algorithm getAlgorithmSelected(){
		return algorithmSelected;
	}
	
	
	
	/*
	 * RECUPERO STRUTTURE
	 */
	public static Hashtable<Integer, MemoryElement> getSOMemory(){
		return SOMemory;
	}
	
	public static List<MemoryElement> getProcessMemory(){
		return processMemory;
	}
	
	public static List<MemoryElement> getSwap(){
		return swap;
	}
	
	public static List<MemoryElement> getEmptyBlockMem(){
		return emptyBlockMem;
	}
	
	public static List<MemoryElement> getEmptyBlockSwap(){
		return emptyBlockSwap;
	}
	
	/*public static List<MemoryElement> getSequenceOutput(){
		return sequence;
	}*/
	
	
	/*
	 * PUNTATORI STRUTTURE
	 */

	public static void setPositionSOMemory(int positionMemoryPara){
		positionSOMemory=positionMemoryPara;
	}
	
	public static int getPositionSOMemory(){
		return positionSOMemory;
	}
	
	
	public static void setPositionProcessMemory(int positionMemoryPara){
		positionProcessMemory=positionMemoryPara;
	}
	
	public static int getPositionProcessMemory(){
		return positionProcessMemory;
	}
	
	public static void setPositionSwap(int positionMemoryPara){
		positionSwap=positionMemoryPara;
	}
	
	public static int getPositionSwap(){
		return positionSwap;
	}
	
	public static void setProcessMemory(List<MemoryElement> ls){
		processMemory = ls;
	}
	
	
	
	/*
	 * DIMENSIONI STRUTTURE
	 */
	
	public static int getDimSOMemory(){
		return dimSOMemory;
	}
	
	public void setDimSOMemory(int dim){
		dimSOMemory=dim;
	}

	public static int getDimProcessMemory(){
		return dimProcessMem;
	}
	
	public static int getDimSwap(){
		return dimSwap;
	}
	
	public static int getDimMemory(){
		return dimMem;
	}
	
	public static boolean isPagination(){
		if (dimPage!=0)
			return true;
		else 
			return false;
	}
	//Creare metodi per restituire i tipi di funzionamento del kernel (paginazione, segmentazione), e algoritmi di sostituzione.

	
	
	
	
	/*
	 * Carica gli algoritmi contenuti nella cartella path.
	 * Gli algoritmi devono avere la classe principale MainAlgo che implementa Algorithm
	 * 
	 */
	
	public static void loadAlgorithm(){
			
			Class cls = null;
			Object o=null;
			String path = "src/it/univpm/diiga/memorysim/kernel/algo/"; 
			//String className = "MainAlgo";
			String archiveType="jar";
			
			File dir = new File (path);
			String className = null;
			String algorithmType = null;
		    JarFile jf;
			
		    

	        /*-- filtro per i file .jar --*/
			FileExtFilter fef = new FileExtFilter(archiveType);
	        String[] list = dir.list (fef);
	        
	        /*-- elenca tutti i file con quella estensione --*/
	        for (int i = 0; i < list.length; i++)
	        {
	        	try {
						File file = new File(path+list[i]);
						URL url = file.toURI().toURL();
						URL[] urls = {url}; 
						//ClassLoader cl = new URLClassLoader(urls);
						//cls = cl.loadClass("FirstFit");
						//o = cls.newInstance();
						
							jf = new JarFile(file);
							Manifest mf = jf.getManifest();
							className = mf.getMainAttributes().getValue(new Attributes.Name("Algorithm-Class"));
							algorithmType = mf.getMainAttributes().getValue(new Attributes.Name("Algortihm-Type"));

						if (className!=null && algorithmType!=null ){
							Class<?> c = new URLClassLoader(urls).loadClass(className);
							o=c.newInstance();
							if(o instanceof Algorithm){
								Algorithm algorithm = (Algorithm) o;
								if(algorithmType.equalsIgnoreCase("paging"))
									algorithmListPag.add(algorithm);
								if(algorithmType.equalsIgnoreCase("segmentation"))
									algorithmListSeg.add(algorithm);
							}
						}
				   
				} catch (MalformedURLException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	        }
		}
	
	public static void setFileSystem(MovingBox root) {
		root_disk= root;
	}
	
	public static void setFileListRequest(ArrayList <FileRequest> files){
		fileList=files;
	}
	
	public void setDimensionCentralMemory(int dimCentralMemory){
		dimMem=dimCentralMemory;
	}

	public void setDimensionSwap(int DimSwap) {
		dimSwap=DimSwap;		
	}

	public void setDimensionBlock(int DimBlock) {
		dimPage=DimBlock;		
	}

	public void setSecondaryMemory(int HD_Dimension,int Seek, int BlockSize,int TrasferRate, int RevolutionTime) {
		dimension=HD_Dimension;
		seekTime=Seek;
		blockSize=BlockSize;
		trasferRate=TrasferRate;
		revolutionTime=RevolutionTime;
	}
	
	public String[] getSecondaryMemoryAlg(){
		return memSecondary;	
	}
	
	public String[] getCentralMemoryAlg(){
		return memCentral;
	}

	public void memstart(ArrayList<String> centralMemoryP,
			ArrayList<String> swapMemoryP) {
		// TODO Auto-generated method stub
		
	}

	public void setProcesses(ArrayList<Process> listProcess) {
		// TODO Auto-generated method stub
		
	}
	
}

	

